package com.gientech.framework.common.config;

import com.gientech.framework.common.core.domain.Result;
import com.gientech.framework.common.enums.BaseStatus;
import com.gientech.framework.common.exception.AuthFailedException;
import com.gientech.framework.common.exception.BusinessException;
import com.gientech.framework.common.exception.ServiceException;
import com.gientech.framework.common.exception.UnknownException;
import com.gientech.framework.common.exception.WarnException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.servlet.http.HttpServletResponse;
import javax.validation.ValidationException;

/**
 * @author gang.tu
 */
@RestControllerAdvice
@ConditionalOnProperty(prefix = "common", value = "enableGlobalControllerAdvice", havingValue = "true", matchIfMissing = true)
public class GlobalControllerAdvice {

    private static final Logger log = LoggerFactory.getLogger(GlobalControllerAdvice.class);

    @ExceptionHandler(value = AuthFailedException.class)
    public Result<Void> authFailedException(AuthFailedException e) {
        log.error(e.getMessage(), e);
        return new Result<>(null, e.getMessage(), e.getCode());
    }

    @ExceptionHandler(value = BusinessException.class)
    public Result<Void> businessException(BusinessException e) {
        log.error(e.getMessage(), e);
        return new Result<>(null, e.getMessage(), e.getCode());
    }

    @ExceptionHandler(value = ServiceException.class)
    public Result<Void> serviceException(ServiceException e) {
        log.error(e.getMessage(), e);
        return new Result<>(null, e.getMessage(), e.getCode());
    }

    @ExceptionHandler(value = {UnknownException.class})
    public Result<Void> unknownException(UnknownException e) {
        log.error(e.getMessage(), e);
        return new Result<>(null, e.getMessage(), e.getCode());
    }

    @ExceptionHandler(Exception.class)
    public Result<Void> exception(Exception e) {
        log.error(e.getMessage(), e);
        return new Result<>(null, e.getMessage(), BaseStatus.FAILED.getCode());
    }

    @ExceptionHandler(value = WarnException.class)
    public Result<Void> warnException(WarnException e) {
        log.warn(e.getMessage(), e);
        return new Result<>(null, e.getMessage(), e.getCode());
    }

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Result<Void> methodArgumentNotValidExceptionHandler(Exception e) {
        log.error(e.getMessage(), e);
        String message = ((MethodArgumentNotValidException) e).getBindingResult().getAllErrors().get(0).getDefaultMessage();
        return new Result<>(null, message, BaseStatus.FAILED.getCode());
    }

    @ExceptionHandler(ValidationException.class)
    public Result<Void> validationException(ValidationException e) {
        log.error(e.getMessage(), e);
        return new Result<>(null, e.getMessage(), BaseStatus.VALIDATION_EXCEPTION.getCode());
    }

    @ExceptionHandler(value = MethodArgumentTypeMismatchException.class)
    public ResponseEntity<Void> methodArgumentTypeMismatchExceptionHandler(MethodArgumentTypeMismatchException e) {
        log.error("入参类型不匹配", e);
        return ResponseEntity.badRequest().body(null);
    }
}
